package com.sz.biz.common.customer.service.impl;

import com.sz.biz.common.constants.CommCodes;
import com.sz.biz.common.constants.ErrorCodes;
import com.sz.biz.common.base.entity.MessageTemplate;
import com.sz.biz.common.customer.entity.CustomerMessageRel;
import com.sz.biz.common.customer.entity.CustomerMessageType;
import com.sz.biz.common.base.service.MessageTemplateService;
import com.sz.biz.common.customer.service.CustomerMessageRelService;
import com.sz.biz.common.customer.service.CustomerMessageRelTypeService;
import com.sz.biz.common.customer.service.CustomerService;
import com.sz.biz.common.customer.dto.CusCustomerDto;
import com.sz.biz.common.customer.dto.CustomerMessageRelTypeItem;
import com.sz.biz.common.customer.dto.NoticeMessageTypeItem;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.exception.Exceptions;
import com.sz.common.base.service.AbstractService;
import com.sz.common.base.utils.FreeMarkerTemplateUtils;
import com.sz.common.core.service.PrincipalUtils;
import com.sz.common.core.system.entity.SysDict;
import com.sz.common.core.system.service.SysDictService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Function: TODO: ADD FUNCTION <br>
 * Author: Johnboy <br>
 * Date: 2017-08-10 17:14:00
 */
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class CustomerMessageRelTypeServiceImpl extends AbstractService implements CustomerMessageRelTypeService {
    @Autowired
    private CustomerService customerService;

    @Autowired
    private CustomerMessageRelService customerMessageRelService;

    @Autowired
    private SysDictService sysDictService;

    @Autowired
    private MessageTemplateService messageTemplateService;

    @Override
    protected String getMapperNamespace() {
        return "CustomerMessageTypeMapper";
    }

    @Override
    public CustomerMessageRelTypeItem getMessageRelTypeTree(Boolean isTree, String localLanguage) {
        ParamData pd = new ParamData();
        pd.put("language", localLanguage);
        List<SysDict> sysDicts = sysDictService.findByCatalog(CommCodes.SYS_DICT_MESSAGE_NOTICE_TYPE);
        List<NoticeMessageTypeItem> noticeMessageTypeItems = new ArrayList<>();
        if (sysDicts != null && sysDicts.size() > 0) {
            for (SysDict sysDict : sysDicts) {
                NoticeMessageTypeItem noticeMessageTypeItem = new NoticeMessageTypeItem();
                BeanUtils.copyProperties(sysDict, noticeMessageTypeItem);
                noticeMessageTypeItems.add(noticeMessageTypeItem);
            }
        }
        BeanUtils.copyProperties(sysDicts, noticeMessageTypeItems);
        List<CustomerMessageType> messageTypes = dao.findForList(getSqlName("listAllTypes"), pd, CustomerMessageType.class);
        if (messageTypes.size() > 0) {
            Map<Integer, CustomerMessageRelTypeItem> messageRelTypeItemMap = new HashMap<>();
            for (CustomerMessageType menu : messageTypes) {
                CustomerMessageRelTypeItem item = new CustomerMessageRelTypeItem(menu);
                for(NoticeMessageTypeItem noticeMessageTypeItem : noticeMessageTypeItems){
                    MessageTemplate messageTemplate = messageTemplateService.findByTemplateTypeAndRefParendId(noticeMessageTypeItem.getCode(),menu.getId());
                    if(messageTemplate!=null){
                        String body =  FreeMarkerTemplateUtils.freeMarkerRender(new HashMap<>(),messageTemplate.getTemplateUrl());
                        noticeMessageTypeItem.setMessageBody(body);
                    }
                }
                item.setMessageTypeItems(noticeMessageTypeItems);
                if (!isTree) {
                    item.setSelected(true);
                }
                messageRelTypeItemMap.put(menu.getId(), item);
            }
            CustomerMessageRelTypeItem root = null;
            for (Map.Entry<Integer, CustomerMessageRelTypeItem> entry : messageRelTypeItemMap.entrySet()) {
                CustomerMessageRelTypeItem item = entry.getValue();
                int parentId = item.getParentId();
                CustomerMessageRelTypeItem parent = messageRelTypeItemMap.get(parentId);
                if (parent != null) {
                    parent.addChild(item);
                }
                else if (parentId == 0) {
                    root = item;
                }
            }
            if (root != null) {
                root.sort();
            }
            return root;
        }
        return null;
    }

    @Override
    public CustomerMessageRelTypeItem getCustomerMessageRelTypeTree(int customerId) {
        if (customerId == 0) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_EMPTY, "customerId");
        }
        String language = PrincipalUtils.getLocalLanguage();
        CusCustomerDto cusCustomerDto = customerService.findById(customerId);
        if (cusCustomerDto == null) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_EMPTY, "customer");
        }
        CustomerMessageRelTypeItem root = getMessageRelTypeTree(false, language);

        List<CustomerMessageRel> customerMessageRels = customerMessageRelService.queryByCustomerId(customerId);

        Map<Integer,CustomerMessageRel> authorizedTypesIdListAndMessageTypes = new HashMap<>();
        customerMessageRels.forEach(customerMessageRel -> authorizedTypesIdListAndMessageTypes.put(customerMessageRel.getRefId(),customerMessageRel));
        removeUnauthorizedMessage(root, authorizedTypesIdListAndMessageTypes);
        return root;
    }

    @Override
    public boolean checkParentIdContainRefIds(int parentId, int refIds) {
        if (parentId == 0 || refIds == 0) {
            return false;
        }
        ParamData pd = new ParamData();
        pd.put("id", refIds);
        pd.put("parentId", parentId);

        List<CustomerMessageType> result = dao.findForList(getSqlName("selectByParentIdAndRefId"), pd, CustomerMessageType.class);
        if (result != null && result.size() > 0) {
            return true;
        }
        return false;
    }

    private boolean removeUnauthorizedMessage(CustomerMessageRelTypeItem item, Map<Integer, CustomerMessageRel> authorizedTypesIdList) {
        if (authorizedTypesIdList.containsKey(item.getId())) {
            return true;
        }
        boolean keepChild = false;
        if (item.hasChild()) {
            for (CustomerMessageRelTypeItem childItem : item.getChildren()) {
                if (removeUnauthorizedMessage(childItem, authorizedTypesIdList)) {
                    keepChild = true;
                    CustomerMessageRel customerMessageRel = authorizedTypesIdList.get(childItem.getId());
                    if (customerMessageRel != null && item.getMessageTypeItems() != null && item.getMessageTypeItems().size() >= 0) {
                        List<String> noticeTypes = Arrays.asList(customerMessageRel.getSendType().split(","));
                        for (NoticeMessageTypeItem noticeMessageTypeItem : item.getMessageTypeItems()) {
                            if (noticeTypes.contains(noticeMessageTypeItem.getCode())) {
                                noticeMessageTypeItem.setSelected(true);
                            }
                        }
                    }
                    if(childItem.getLeaf()){
                        childItem.setMessageTypeItems(null);
                    }
                }
                else {
                    childItem.setSelected(false);
                    if(childItem.getLeaf()){
                        childItem.setMessageTypeItems(null);
                    }
                }
            }
        }
        return keepChild;
    }
}
